package com.hang.service;

import com.hang.datasource.DynamicDataSource;
import com.hang.entity.TenantDataSource;
import com.hang.mapper.TenantDataSourceMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import org.springframework.stereotype.Service;

import javax.sql.DataSource;
import java.lang.reflect.Field;
import java.util.Map;

@Service
public class TenantDataSourceService {
    @Autowired
    private TenantDataSourceMapper tenantDataSourceMapper;
    @Autowired
    private DataSource dynamicDataSource;

    /**
     * 加载并注册租户数据源
     */
    public void loadAndRegisterDataSource(String tenantCode) {
        // 1. 检查是否已注册
        Map<Object, Object> dataSources = getCurrentDataSources();
        if (dataSources.containsKey(tenantCode)) return;

        // 2. 查询主库获取租户数据源配置
        TenantDataSource config = tenantDataSourceMapper.selectByTenantCode(tenantCode);
        if (config == null) {
            throw new RuntimeException("租户不存在: " + tenantCode);
        }

        // 3. 动态注册数据源
        DataSource newDataSource = DataSourceBuilder.create()
                .url(config.getUrl())
                .username(config.getUsername())
                .password(config.getPassword())
                .driverClassName(config.getDriverClassName())
                .build();
        dataSources.put(tenantCode, newDataSource);
        ((DynamicDataSource) dynamicDataSource).setTargetDataSources(dataSources);
        ((DynamicDataSource) dynamicDataSource).afterPropertiesSet();
    }

    /**
     * 获取当前所有数据源（反射实现）
     */
    private Map<Object, Object> getCurrentDataSources() {
        try {
            Field targetDataSourcesField = AbstractRoutingDataSource.class.getDeclaredField("targetDataSources");
            targetDataSourcesField.setAccessible(true);
            return (Map<Object, Object>) targetDataSourcesField.get(dynamicDataSource);
        } catch (Exception e) {
            throw new RuntimeException("获取数据源失败", e);
        }
    }

    public void registerDataSource(String tenantCode, TenantDataSource config) {
        Map<Object, Object> dataSources = getCurrentDataSources();
        if (dataSources.containsKey(tenantCode)) return;

        DataSource newDataSource = DataSourceBuilder.create()
                .url(config.getUrl())
                .username(config.getUsername())
                .password(config.getPassword())
                .driverClassName(config.getDriverClassName())
                .build();
        dataSources.put(tenantCode, newDataSource);
        ((DynamicDataSource) dynamicDataSource).setTargetDataSources(dataSources);
        ((DynamicDataSource) dynamicDataSource).afterPropertiesSet();
    }
}
